package cn.xiaoyu.su.service.impl;

import cn.xiaoyu.su.config.RabbitMQConfig;
import cn.xiaoyu.su.constant.CacheKey;
import cn.xiaoyu.su.enums.AuthEnum;
import cn.xiaoyu.su.enums.BizCodeEnum;
import cn.xiaoyu.su.enums.EventMessageType;
import cn.xiaoyu.su.enums.SendCodeEnum;
import cn.xiaoyu.su.model.AccountDO;
import cn.xiaoyu.su.mapper.AccountMapper;
import cn.xiaoyu.su.model.EventMessage;
import cn.xiaoyu.su.model.LoginUser;
import cn.xiaoyu.su.controller.request.LoginRequest;
import cn.xiaoyu.su.controller.request.UserRegisterRequest;
import cn.xiaoyu.su.service.AccountService;
import cn.xiaoyu.su.util.CommonUtil;
import cn.xiaoyu.su.util.IDUtil;
import cn.xiaoyu.su.util.JWTUtil;
import cn.xiaoyu.su.util.JsonData;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.digest.Md5Crypt;
import org.apache.commons.lang3.StringUtils;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author ⼆当家⼩D
 * @since 2022-10-27
 */
@Service
@Slf4j
public class AccountServiceImpl  implements AccountService {

    @Autowired
    private AccountMapper accountMapper;

    @Autowired
    private StringRedisTemplate redisTemplate;

    /**
     * 免费流量包固定商品id
     */
    private static final Long FREE_TRAFFIC_PRODUCT_ID = 1L;

    @Autowired
    private RabbitMQConfig rabbitMQConfig;

    @Autowired
    private RabbitTemplate rabbitTemplate;

    /**
     * 新用户注册
     * @param userRegisterRequest
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class,propagation = Propagation.REQUIRED)
    public JsonData register(UserRegisterRequest userRegisterRequest) {

        boolean flag = checkCode(userRegisterRequest.getCode(),userRegisterRequest.getPhone());

        if (!flag) {
            log.error("验证码错误：{}",userRegisterRequest.toString());
            return JsonData.buildResult(BizCodeEnum.CODE_ERROR);
        }

        if (checkUnique(userRegisterRequest.getPhone())) {
            String secret = "$1$" + CommonUtil.getStringNumRandom(6);
            String cryptPwd = Md5Crypt.md5Crypt(userRegisterRequest.getPwd().getBytes(), secret);


            AccountDO accountDO = new AccountDO();
            //生成唯一的账号 TODO
            //accountDO.setAccountNo(Long.parseLong(CommonUtil.getRandomCode(13)));
            accountDO.setAccountNo(Long.parseLong(IDUtil.geneSnowFlakeID().toString()));
            accountDO.setAuth(AuthEnum.DEFAULT.name());
            accountDO.setHeadImg("oss");
            accountDO.setMail(userRegisterRequest.getMail());
            accountDO.setPhone(userRegisterRequest.getPhone());
            accountDO.setPwd(cryptPwd);
            accountDO.setSecret(secret);
            accountDO.setUsername(userRegisterRequest.getUsername());

            accountMapper.insert(accountDO);

            userRegisterInitTask(accountDO);

            return JsonData.buildSuccess();
        } else {
            log.error("账户已存在：{}",userRegisterRequest.toString());
            return JsonData.buildResult(BizCodeEnum.ACCOUNT_REPEAT);
        }

    }

    /**
     * 登录
     * @param loginRequest
     * @return
     */
    @Override
    public JsonData login(LoginRequest loginRequest) {

        AccountDO accountDO = accountMapper.selectOne(new QueryWrapper<AccountDO>().eq("phone", loginRequest.getPhone()));

        if (accountDO == null) {
            log.error("账号不存在：{}",loginRequest.toString());
            return JsonData.buildResult(BizCodeEnum.ACCOUNT_UNREGISTER);
        }

        String cryptPwd = Md5Crypt.md5Crypt(loginRequest.getPwd().getBytes(), accountDO.getSecret());

        if (!cryptPwd.equalsIgnoreCase(accountDO.getPwd())) {
            log.error("密码错误：{}",loginRequest.toString());
            return JsonData.buildResult(BizCodeEnum.ACCOUNT_PWD_ERROR);
        }

        LoginUser loginUser = LoginUser.builder()
                .mail(accountDO.getMail())
                .headImg(accountDO.getHeadImg())
                .accountNo(accountDO.getAccountNo())
                .auth(accountDO.getAuth())
                .phone(accountDO.getPhone())
                .username(accountDO.getUsername())
                .build();

        String token = JWTUtil.geneJsonWebToken(loginUser);

        return JsonData.buildSuccess(token);
    }

    private boolean checkUnique(String phone) {

        AccountDO accountDO = accountMapper.selectOne(new QueryWrapper<AccountDO>().eq("phone", phone));

        if (accountDO == null) {
            return true;
        }

        return false;
    }

    private boolean checkCode(String code, String phone) {

        String cacheKey = String.format(CacheKey.SEND_CODE_KEY, SendCodeEnum.REGISTER.name(),phone);

        String cahceValue = redisTemplate.opsForValue().get(cacheKey);

        if (StringUtils.isNotBlank(cahceValue)) {

            String cacheCode = cahceValue.split("_")[0];

            if (cacheCode.equalsIgnoreCase(code)) {

                redisTemplate.delete(cacheKey);

                return true;
            }

        }

        return false;
    }

    /**
     * 用户初始化，发放福利：流量包
     * @param accountDO
     */
    private void userRegisterInitTask(AccountDO accountDO) {

        EventMessage eventMessage = EventMessage.builder()
                .messageId(IDUtil.geneSnowFlakeID().toString())
                .accountNo(accountDO.getAccountNo())
                .eventMessageType(EventMessageType.TRAFFIC_FREE_INIT.name())
                .bizId(FREE_TRAFFIC_PRODUCT_ID.toString())
                .build();
        //发放流量包消息
        rabbitTemplate.convertAndSend(rabbitMQConfig.getTrafficEventExchange(),rabbitMQConfig.getTrafficFreeInitRoutingKey(),eventMessage);

    }
}
